package com.cencat.merchant.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cencat.merchant.entity.Route;
import com.cencat.merchant.dto.RouteQueryDTO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 路线管理Mapper接口
 * 提供路线数据的增删改查、统计分析、智能匹配等数据访问功能
 * 
 * @author cencat
 * @version 1.0
 * @since 2025-01-20
 */
@Mapper
public interface RouteMapper extends BaseMapper<Route> {

    /**
     * 分页查询路线列表
     * 
     * @param page 分页参数
     * @param queryDTO 查询条件
     * @return 路线分页数据
     */
    Page<Route> selectRoutePage(Page<Route> page, @Param("query") RouteQueryDTO queryDTO);

    /**
     * 批量更新路线状态
     * 
     * @param ids 路线ID列表
     * @param status 新状态
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE route SET status = #{status}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdateStatus(@Param("ids") List<Long> ids, @Param("status") String status);

    /**
     * 批量更新路线发布状态
     * 
     * @param ids 路线ID列表
     * @param publishStatus 发布状态
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE route SET publish_status = #{publishStatus}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdatePublishStatus(@Param("ids") List<Long> ids, @Param("publishStatus") String publishStatus);

    /**
     * 批量更新路线优先级
     * 
     * @param ids 路线ID列表
     * @param priority 优先级
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE route SET priority = #{priority}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdatePriority(@Param("ids") List<Long> ids, @Param("priority") Integer priority);

    /**
     * 批量更新路线价格
     * 
     * @param ids 路线ID列表
     * @param price 价格
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE route SET price = #{price}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdatePrice(@Param("ids") List<Long> ids, @Param("price") BigDecimal price);

    /**
     * 根据状态统计路线数量
     * 
     * @param status 路线状态
     * @return 路线数量
     */
    @Select("SELECT COUNT(*) FROM route WHERE status = #{status}")
    Long countByStatus(@Param("status") String status);

    /**
     * 根据路线类型统计路线数量
     * 
     * @param routeType 路线类型
     * @return 路线数量
     */
    @Select("SELECT COUNT(*) FROM route WHERE route_type = #{routeType}")
    Long countByRouteType(@Param("routeType") String routeType);

    /**
     * 计算平均路线价格
     * 
     * @return 平均价格
     */
    @Select("SELECT AVG(price) FROM route WHERE status = 'ACTIVE'")
    BigDecimal calculateAveragePrice();

    /**
     * 查询活跃路线列表
     * 
     * @param limit 限制数量
     * @return 活跃路线列表
     */
    @Select("SELECT * FROM route WHERE status = 'ACTIVE' ORDER BY update_time DESC LIMIT #{limit}")
    List<Route> selectActiveRoutes(@Param("limit") Integer limit);

    /**
     * 查询已发布路线列表
     * 
     * @param limit 限制数量
     * @return 已发布路线列表
     */
    @Select("SELECT * FROM route WHERE publish_status = 'PUBLISHED' ORDER BY update_time DESC LIMIT #{limit}")
    List<Route> selectPublishedRoutes(@Param("limit") Integer limit);

    /**
     * 查询热门路线列表
     * 
     * @param limit 限制数量
     * @return 热门路线列表
     */
    @Select("SELECT * FROM route WHERE status = 'ACTIVE' ORDER BY order_count DESC, update_time DESC LIMIT #{limit}")
    List<Route> selectPopularRoutes(@Param("limit") Integer limit);

    /**
     * 查询推荐路线列表
     * 
     * @param limit 限制数量
     * @return 推荐路线列表
     */
    @Select("SELECT * FROM route WHERE is_recommended = 1 AND status = 'ACTIVE' ORDER BY priority DESC, update_time DESC LIMIT #{limit}")
    List<Route> selectRecommendedRoutes(@Param("limit") Integer limit);

    /**
     * 根据路线类型查询路线列表
     * 
     * @param routeType 路线类型
     * @param status 路线状态
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("<script>" +
            "SELECT * FROM route WHERE route_type = #{routeType} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Route> selectRoutesByType(@Param("routeType") String routeType, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 根据价格范围查询路线列表
     * 
     * @param minPrice 最小价格
     * @param maxPrice 最大价格
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("SELECT * FROM route WHERE price BETWEEN #{minPrice} AND #{maxPrice} " +
            "ORDER BY price ASC LIMIT #{limit}")
    List<Route> selectRoutesByPriceRange(@Param("minPrice") BigDecimal minPrice, @Param("maxPrice") BigDecimal maxPrice, @Param("limit") Integer limit);

    /**
     * 根据距离范围查询路线列表
     * 
     * @param minDistance 最小距离
     * @param maxDistance 最大距离
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("SELECT * FROM route WHERE distance BETWEEN #{minDistance} AND #{maxDistance} " +
            "ORDER BY distance ASC LIMIT #{limit}")
    List<Route> selectRoutesByDistanceRange(@Param("minDistance") BigDecimal minDistance, @Param("maxDistance") BigDecimal maxDistance, @Param("limit") Integer limit);

    /**
     * 根据创建时间范围查询路线列表
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("SELECT * FROM route WHERE create_time BETWEEN #{startTime} AND #{endTime} " +
            "ORDER BY create_time DESC LIMIT #{limit}")
    List<Route> selectRoutesByCreateTime(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("limit") Integer limit);

    /**
     * 根据起点和终点查询路线
     * 
     * @param startCity 起点城市
     * @param endCity 终点城市
     * @param status 路线状态
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("<script>" +
            "SELECT * FROM route WHERE start_city = #{startCity} AND end_city = #{endCity} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY price ASC, update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Route> selectRoutesByStartAndEnd(@Param("startCity") String startCity, @Param("endCity") String endCity, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 根据起点查询路线
     * 
     * @param startCity 起点城市
     * @param status 路线状态
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("<script>" +
            "SELECT * FROM route WHERE start_city = #{startCity} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Route> selectRoutesByStartCity(@Param("startCity") String startCity, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 根据终点查询路线
     * 
     * @param endCity 终点城市
     * @param status 路线状态
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("<script>" +
            "SELECT * FROM route WHERE end_city = #{endCity} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status} " +
            "</if>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Route> selectRoutesByEndCity(@Param("endCity") String endCity, @Param("status") String status, @Param("limit") Integer limit);

    /**
     * 智能匹配路线
     * 
     * @param startCity 起点城市
     * @param endCity 终点城市
     * @param routeType 路线类型
     * @param maxPrice 最大价格
     * @param maxDistance 最大距离
     * @param limit 限制数量
     * @return 匹配的路线列表
     */
    @Select("<script>" +
            "SELECT * FROM route " +
            "WHERE status = 'ACTIVE' " +
            "AND publish_status = 'PUBLISHED' " +
            "AND start_city = #{startCity} " +
            "AND end_city = #{endCity} " +
            "<if test='routeType != null and routeType != \"\">" +
            "AND route_type = #{routeType} " +
            "</if>" +
            "<if test='maxPrice != null'>" +
            "AND price <= #{maxPrice} " +
            "</if>" +
            "<if test='maxDistance != null'>" +
            "AND distance <= #{maxDistance} " +
            "</if>" +
            "ORDER BY priority DESC, price ASC, distance ASC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Route> selectMatchedRoutes(@Param("startCity") String startCity, @Param("endCity") String endCity, @Param("routeType") String routeType, @Param("maxPrice") BigDecimal maxPrice, @Param("maxDistance") BigDecimal maxDistance, @Param("limit") Integer limit);

    /**
     * 检查路线编码是否存在
     * 
     * @param routeCode 路线编码
     * @param excludeId 排除的路线ID
     * @return 存在数量
     */
    @Select("<script>" +
            "SELECT COUNT(*) FROM route WHERE route_code = #{routeCode} " +
            "<if test='excludeId != null'>" +
            "AND id != #{excludeId}" +
            "</if>" +
            "</script>")
    int existsByRouteCode(@Param("routeCode") String routeCode, @Param("excludeId") Long excludeId);

    /**
     * 搜索路线
     * 
     * @param keyword 关键词
     * @param searchType 搜索类型
     * @param limit 限制数量
     * @return 路线列表
     */
    @Select("<script>" +
            "SELECT * FROM route WHERE 1=1 " +
            "<choose>" +
            "<when test='searchType == \"name\"'>" +
            "AND route_name LIKE CONCAT('%', #{keyword}, '%') " +
            "</when>" +
            "<when test='searchType == \"code\"'>" +
            "AND route_code LIKE CONCAT('%', #{keyword}, '%') " +
            "</when>" +
            "<when test='searchType == \"city\"'>" +
            "AND (start_city LIKE CONCAT('%', #{keyword}, '%') " +
            "OR end_city LIKE CONCAT('%', #{keyword}, '%')) " +
            "</when>" +
            "<otherwise>" +
            "AND (route_name LIKE CONCAT('%', #{keyword}, '%') " +
            "OR route_code LIKE CONCAT('%', #{keyword}, '%') " +
            "OR start_city LIKE CONCAT('%', #{keyword}, '%') " +
            "OR end_city LIKE CONCAT('%', #{keyword}, '%')) " +
            "</otherwise>" +
            "</choose>" +
            "ORDER BY update_time DESC " +
            "<if test='limit != null'>" +
            "LIMIT #{limit}" +
            "</if>" +
            "</script>")
    List<Route> searchRoutes(@Param("keyword") String keyword, @Param("searchType") String searchType, @Param("limit") Integer limit);

    /**
     * 查询路线列表（用于导出）
     * 
     * @param queryDTO 查询条件
     * @return 路线列表
     */
    List<Route> selectRouteList(@Param("query") RouteQueryDTO queryDTO);

    /**
     * 计算指定时间范围内的路线数量
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param status 路线状态
     * @return 路线数量
     */
    @Select("<script>" +
            "SELECT COUNT(*) FROM route " +
            "WHERE create_time BETWEEN #{startTime} AND #{endTime} " +
            "<if test='status != null and status != \"\">" +
            "AND status = #{status}" +
            "</if>" +
            "</script>")
    Integer calculateRouteCount(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("status") String status);

    /**
     * 计算指定时间范围内的平均价格
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 平均价格
     */
    @Select("SELECT AVG(price) FROM route WHERE create_time BETWEEN #{startTime} AND #{endTime}")
    Double calculateAveragePriceByTime(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取路线趋势数据
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param trendType 趋势类型
     * @return 趋势数据
     */
    List<Map<String, Object>> selectRouteTrends(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime, @Param("trendType") String trendType);

    /**
     * 获取路线排行榜
     * 
     * @param rankType 排行类型
     * @param limit 限制数量
     * @return 排行榜数据
     */
    List<Map<String, Object>> selectRouteRanking(@Param("rankType") String rankType, @Param("limit") Integer limit);

    /**
     * 获取路线分布数据
     * 
     * @param distributionType 分布类型
     * @return 分布数据
     */
    List<Map<String, Object>> selectRouteDistribution(@Param("distributionType") String distributionType);

    /**
     * 更新路线订单数量
     * 
     * @param routeId 路线ID
     * @param orderCount 订单数量
     * @return 更新记录数
     */
    @Update("UPDATE route SET order_count = #{orderCount}, update_time = NOW() WHERE id = #{routeId}")
    int updateOrderCount(@Param("routeId") Long routeId, @Param("orderCount") Integer orderCount);

    /**
     * 更新路线评分
     * 
     * @param routeId 路线ID
     * @param rating 评分
     * @return 更新记录数
     */
    @Update("UPDATE route SET rating = #{rating}, update_time = NOW() WHERE id = #{routeId}")
    int updateRouteRating(@Param("routeId") Long routeId, @Param("rating") BigDecimal rating);

    /**
     * 更新路线推荐状态
     * 
     * @param routeId 路线ID
     * @param isRecommended 是否推荐
     * @return 更新记录数
     */
    @Update("UPDATE route SET is_recommended = #{isRecommended}, update_time = NOW() WHERE id = #{routeId}")
    int updateRecommendedStatus(@Param("routeId") Long routeId, @Param("isRecommended") Boolean isRecommended);

    /**
     * 批量更新路线推荐状态
     * 
     * @param routeIds 路线ID列表
     * @param isRecommended 是否推荐
     * @return 更新记录数
     */
    @Update("<script>" +
            "UPDATE route SET is_recommended = #{isRecommended}, update_time = NOW() " +
            "WHERE id IN " +
            "<foreach collection='routeIds' item='id' open='(' separator=',' close=')'>" +
            "#{id}" +
            "</foreach>" +
            "</script>")
    int batchUpdateRecommendedStatus(@Param("routeIds") List<Long> routeIds, @Param("isRecommended") Boolean isRecommended);

    /**
     * 获取路线统计数据
     * 
     * @param routeId 路线ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 统计数据
     */
    Map<String, Object> selectRouteStats(@Param("routeId") Long routeId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取路线收入统计
     * 
     * @param routeId 路线ID
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 收入统计数据
     */
    Map<String, Object> selectRouteIncomeStats(@Param("routeId") Long routeId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);

    /**
     * 获取路线评价统计
     * 
     * @param routeId 路线ID
     * @return 评价统计数据
     */
    Map<String, Object> selectRouteRatingStats(@Param("routeId") Long routeId);

    /**
     * 获取热门城市路线
     * 
     * @param limit 限制数量
     * @return 热门城市路线数据
     */
    List<Map<String, Object>> selectPopularCityRoutes(@Param("limit") Integer limit);

    /**
     * 获取路线价格分析
     * 
     * @param routeType 路线类型
     * @param startCity 起点城市
     * @param endCity 终点城市
     * @return 价格分析数据
     */
    Map<String, Object> selectRoutePriceAnalysis(@Param("routeType") String routeType, @Param("startCity") String startCity, @Param("endCity") String endCity);
}